package com.apobates.forum.toro.template;

import com.apobates.forum.toro.AbstractMapper;
import com.apobates.forum.toro.BatchQueryFace;
import com.apobates.forum.toro.ResultMapperTransfer;
import com.apobates.forum.toro.template.strategy.TemplateBasisStrategy;
import com.apobates.forum.toro.template.strategy.TemplateBatchStrategy;
import com.apobates.forum.toro.template.strategy.TemplateSerialBasisStrategy;
import com.apobates.forum.toro.template.strategy.TemplateSerialBatchStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 模板映射执行器
 * @param <E> 目标对象Class
 * @param <T> 初始对象类型
 * @author xiaofanku@live.cn
 * @since 2022-09-03
 */
public class TemplateMapperExecutor<E,T> extends AbstractMapper<E,T> {
    private final static Logger logger = LoggerFactory.getLogger(TemplateMapperExecutor.class);
    public TemplateMapperExecutor(Supplier<Collection<T>> origin, Class<E> className, boolean isConcurrent, boolean isMany) {
        super(origin, className, isConcurrent, isMany);
    }

    /**
     * [单实例]设置最终结果的处理函数,包括: 消费函数 & 映射函数
     * @param transfer 最终结果处理函数
     * @return
     */
    public <F> BasisHandler<F> basis(ResultMapperTransfer<E,F> transfer) {
        return new BasisHandler<>(transfer);
    }

    /**
     * [单实例]设置最终结果的消费函数
     * @param consumer 消费函数/前置处理
     * @return
     */
    public BasisHandler<E> basis(Consumer<E> consumer) {
        ResultMapperTransfer<E,E> transfer = new ResultMapperTransfer<>(){
            @Override
            public Consumer<E> getConsumer() {
                return consumer;
            }
            @Override
            public Function<E, E> getFormater() {
                return Function.identity();
            }
        };
        return new BasisHandler<>(transfer);
    }

    /**
     * [单实例]设置最终结果的映射函数
     * @param formater 映射函数/后置转换
     * @return
     * @param <F>
     */
    public <F> BasisHandler<F> basis(Function<E,F> formater) {
        ResultMapperTransfer<E,F> transfer = new ResultMapperTransfer<>(){
            @Override
            public Consumer<E> getConsumer() {
                return (E ins)->logger.info("TemplateMapperExecutor.BasisHandler Default Consumer");
            }
            @Override
            public Function<E, F> getFormater() {
                return formater;
            }
        };
        return new BasisHandler<>(transfer);
    }

    /**
     * [单实例]绑定基础关系语句
     * @return
     * @param <F>
     */
    public <F> BasisHandler<F> basis() {
        return new BasisHandler<>(ResultMapperTransfer.empty());
    }

    /**
     * [实例集合]设置最终结果的处理函数,包括: 消费函数 & 映射函数
     * @param transfer 最终结果处理函数
     * @return
     */
    public <F> BatchHandler<F> batch(ResultMapperTransfer<E,F> transfer) {
        return new BatchHandler<>(transfer);
    }

    /**
     * [实例集合]设置最终结果的消费函数
     * @param consumer 消费函数/前置处理
     * @return
     */
    public BatchHandler<E> batch(Consumer<E> consumer) {
        ResultMapperTransfer<E,E> transfer = new ResultMapperTransfer<>(){
            @Override
            public Consumer<E> getConsumer() {
                return consumer;
            }
            @Override
            public Function<E, E> getFormater() {
                return Function.identity();
            }
        };
        return new BatchHandler<>(transfer);
    }

    /**
     * [实例集合]设置最终结果的映射函数
     * @param formater 映射函数/后置转换
     * @return
     * @param <F>
     */
    public <F> BatchHandler<F> batch(Function<E,F> formater) {
        ResultMapperTransfer<E,F> transfer = new ResultMapperTransfer<>(){
            @Override
            public Consumer<E> getConsumer() {
                return (E ins)->logger.info("TemplateMapperExecutor.BatchHandler Default Consumer");
            }
            @Override
            public Function<E, F> getFormater() {
                return formater;
            }
        };
        return new BatchHandler<>(transfer);
    }

    /**
     * [实例集合]绑定批量关系语句
     * @return
     * @param <F>
     */
    public <F> BatchHandler<F> batch() {
        return new BatchHandler(ResultMapperTransfer.empty());
    }

    /**
     * 创建属性前缀模板映射执行器
     * @return
     */
    public TemplateAffixMapperExecutor<E,T> affix(){
        // Supplier<Collection<T>> selectObjSet, Class<E> className, boolean concurrent
        return new TemplateAffixMapperExecutor(getOrigin(), getClassName(), isConcurrent());
    }
    /**
     * 基础(单)执行句柄
     */
    public class BasisHandler<F>{
        private final ResultMapperTransfer<E,F> transfer;
        private Map<String, Function<String,?>> queries = new HashMap<>();
        public BasisHandler(ResultMapperTransfer<E,F> transfer) {
            this.transfer = transfer;
        }
        /**
         * 绑定标签和目标对象
         * @param tag 标签名，用于分组不同的聚合字段属于哪个类。例: Members
         * @param selectFunction 标签相关的对象映射函数
         * @return
         */
        public BasisHandler compose(String tag, Function<String,?> selectFunction) {
            this.queries.put(tag, selectFunction);
            return this;
        }

        /**
         * 使用指定策略返回结果
         * @param strategy 聚合策略
         * @return
         */
        public Optional<F> get(List<TemplateStatements> statements, TemplateBasisStrategy<E,T> strategy) {
            T selectObj = new ArrayList<>(getOrigin().get()).get(0);
            Optional<E> rs = strategy.apply(getClassName(), selectObj, statements, queries);
            return this.transfer.get(rs);
        }

        /**
         * 使用内置的TemplateSerialBasisStrategy策略返回结果
         * @return
         */
        public Optional<F> get(List<TemplateStatements> statements) {
            return get(statements, new TemplateSerialBasisStrategy<>());
        }
    }

    /**
     * 批量执行句柄
     */
    public class BatchHandler<F>{
        private final ResultMapperTransfer<E,F> transfer;
        private Map<String, BatchQueryFace> queries = new HashMap<>();
        public BatchHandler(ResultMapperTransfer<E,F> transfer) {
            this.transfer = transfer;
        }
        /**
         * 绑定标签和目标对象
         * @param tag 标签名，用于分组不同的聚合字段属于哪个类。例: Members
         * @param selectFunction 标签相关的对象映射函数
         * @return
         */
        public BatchHandler compose(String tag, BatchQueryFace selectFunction) {
            this.queries.put(tag, selectFunction);
            return this;
        }

        /**
         * 使用指定策略返回结果
         * @param strategy 聚合策略
         * @return
         */
        public Collection<F> get(List<TemplateStatements> statements, TemplateBatchStrategy<E,T> strategy) {
            Collection<E> rs = strategy.apply(getClassName(), getOrigin().get(), statements, queries);
            return this.transfer.getAll(rs);
        }

        /**
         * 使用内置的TemplateSerialBatchStrategy策略返回结果
         * @return
         */
        public Collection<F> get(List<TemplateStatements> statements) {
            return get(statements, new TemplateSerialBatchStrategy<>());
        }
    }
}
